#include "threadpool.h"
#include "queue.h"

/*
函数功能：线程池创建
函数参数：1.队列长度  2.线程个数  3.线程运行的代码起始地址，即在此线程中运行哪段代码。是一个函数指针类型，通常传递一个函数的名字。
函数返回：结构体指针
*/
struct threadPool *createThreadPool(int max_queue_length, int threads, void *(*consumer)(void *))
{
	struct threadPool *pool = NULL;
	pool = (struct threadPool *)malloc(sizeof(struct threadPool));
	
	if(pool == NULL)
	{
		perror("malloc");  //内存分配失败
		return NULL;
	}
	memset(pool, 0, sizeof(struct threadPool));
	
	//给线程ID申请空间
														   //线程个数
	pool -> tids = (pthread_t *)malloc(sizeof(pthread_t) * threads);

	if(pool -> tids == NULL)
	{
		perror("malloc");  //内存分配失败
		return NULL;
	}
	
	//功能：初始化信号量
	//函数原型：int sem_init(sem_t *sem, int pshared, unsigned int value);
	//函数参数：1.sem：指向信号量结构的一个指针； 2.pshared：决定信号量能否在几个进程间共享。由于目前Linux还没有实现进程间共享信号量，所以这个值只能为0，就表示这个信号量是当前进程的所有线程共享； 3.value 参数指定信号量的初始值。
	//函数返回：成功：返回 0；失败：返回-1
								 //队列长度
	sem_init(&pool -> semw, 0, max_queue_length);

	sem_init(&pool -> semr, 0, 0);
	
	//功能：初始化互斥锁
	//函数原型：int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
	//1.mutex: 被初始化的互斥锁
	//2.attr: 新建立互斥锁属性，如果参数attr为空，则默认使用互斥锁属性，默认属性为快速互斥锁
	pthread_mutex_init(&pool -> mutex, NULL);

	//创建队列
	pool -> que = create_queue();

	pool -> max_queue_length = max_queue_length;

	int retval = 0;
	//创建含有threads个消费者线程的线程池，给每一个线程传递pool
	for(int i = 0; i < threads; i++)
	{
		//函数功能：创建一个新的线程
		//函数原型：int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
		//函数参数：第1个参数用来存储线程ID，参数为指向线程ID的指针在目前版本的Linux下，线程的ID在某个进程中是唯一的。
		//第2个参数用来设置线程属性，主要设置与栈相关的属性。一般情况下，此参数设置为 NULL，新的线程将使用系统默认的属性。
		//第3个参数是线程运行的代码起始地址，即在此线程中运行哪段代码。是一个函数指针类型，通常传递一个函数的名字。
		//第4个参数是线程函数的参数。是一个void*类型的指针，如果需要传入多个参数，则需要使用一个包含这些参数的结构体地址。
									//指针数组
		retval = pthread_create(&pool -> tids[i], NULL, consumer, pool);
		//此函数如果执行成功，将返回 0，如果失败，将返回非 0 值。
		if(retval != 0)
		{
			perror("pthread_create error");   //线程创建失败
			exit(-1);
		}
	}

	return pool;
}

//销毁线程池函数
void destroyThreadPool(struct threadPool *pool, int threads)
{
	//回收线程资源
	for(int i = 0; i < threads; i++)
	{
		//功能：此函数将阻塞调用当前线程的线程，直到此线程退出。当函数返回时，处于被等待状态的线程资源被收回。
		//函数原型：int pthread_join(pthread_t thread, void **retval);
		//函数参数：1.第1个参数为被等待的线程ID  2.第2个参数为一个用户定义的指针,指向一个保存等待线程的完整退出状态的静态区域它可以用来存储被等待线程的返回值。
		pthread_join(pool -> tids[i], NULL);
	}
	
	//先释放结构体内部元素空间，再释放整个结构体空间
	
	//释放空间
	free(pool -> tids);

	//函数功能：释放信号量
	//函数原型：int sem_destroy (sem_t *sem);
	//参数说明：1.sem：指向信号量结构的一个指针。
	//函数返回值：成功：返回0；失败：返回-1。
	sem_destroy(&pool -> semw);
	sem_destroy(&pool -> semr);

	//函数功能：销毁互斥锁
	//函数原型：int pthread_mutex_destroy(pthread_mutex_t *mutex);
	//函数参数：1.mutex：需要被释放的锁变量对象。
	//成功：返回 0；失败：返回错误号
	pthread_mutex_destroy(&pool -> mutex);

	//释放队列
	freeLink(pool -> que);

	free(pool);
}

